import G6 from '@antv/g6';
import { Tsrv } from '../o-graph/config';

function getSetState(name, value, item) {
  const nodeModel = item.getModel();
  const nodeStroke = nodeModel[`stroke`] || '#6ab7ff';
  const nodeFill = nodeModel[`fill`] || '#fff';
  const group = item.getContainer();
  if (!group.get('children')) {
    return;
  }
  const shape = group.get('children')[0];

  const children = group.findAll(g => {
    return g.attrs.parent === shape.attrs.id;
  });
  const circles = group.findAll(circle => {
    return circle.attrs.isInPoint || circle.attrs.isOutPoint;
  });
  const selectStyles = () => {
    shape.attr('fill', '#f3f9ff');
    shape.attr('stroke', '#ffa0a3');
    shape.attr('cursor', 'move');
    children.forEach(child => {
      child.attr('cursor', 'move');
    });
    circles.forEach(circle => {
      circle.attr('opacity', 1);
    });
  };
  const unSelectStyles = () => {
    shape.attr('fill', nodeFill);
    shape.attr('stroke', nodeStroke);
    circles.forEach(circle => {
      circle.attr('opacity', 0);
    });
  };

  switch (name) {
    case 'selected':
    case 'hover':
      if (value) {
        selectStyles();
      } else {
        unSelectStyles();
      }
      break;
    case 'changeLabel':
      break;
    default:
      throw new Error(`err`);
  }
}

function getNodeAttr(
  anchorPointName: string,
  x: number,
  y: number,
  parentId: string,
  type: string,
  isChild: boolean
) {
  if (!isChild) {
    // 主图
    return {
      attrs: {
        id: `circle${Tsrv.utils.custUUID(16, 16)}`,
        parent: parentId,
        x,
        y,
        r: 20,
        isInPointOut: type === 'inOut' ? true : type === 'in',
        isOutPointOut: type === 'inOut' ? true : type !== 'in',
        anchorPointName, // 锚点名
        fill: '#1890ff',
        opacity: 0 // 默認0 需要時改成0.3
      }
    };
  }
  return {
    attrs: {
      id: parentId,
      x,
      y,
      r: 8,
      isInPoint: type === 'inOut' ? true : type === 'in',
      isOutPoint: type === 'inOut' ? true : type !== 'in',
      anchorPointName, // 用于指定连接点的属性，例如在 条件节点 指定 输出连接点为判断YES/NO
      fill: '#fff',
      stroke: '#1890ff',

      opacity: 0
    }
  };
}

function getLabelAttr(
  name: string,
  draggable: boolean,
  x: number,
  y: number,
  cfg: any,
  parentId: string
): any {
  const lableText = cfg.label || ``;
  const labelFill = cfg.labelFill || '#565758';
  const labelFontSize = cfg.labelFontSize || 22;
  return {
    name,
    draggable,
    attrs: {
      id: `label${Tsrv.utils.custUUID(16, 16)}`,
      x,
      y,
      textAlign: 'center',
      textBaseline: 'middle',
      fontSize: labelFontSize,
      text: lableText,
      parent: parentId,
      fill: labelFill
    }
  };
}
function autoLableSize() {}
function afterNodeDraw(cfg, node) {}
function nodeUpdate(cfg, node) {
  // 节点或边上的文本超长时，可以通过使用 JS 来计算文本长度，也可以通过使用
  // 来进行换行。G6 提供了 Util.getLetterWidth 与 Util.getTextSize 辅助计算文本长度，但仅适用于默认字体。

  // // 根据label宽度自动宽度
  // const labelWidth: number = node._cfg.group
  //   .getCanvas()
  //   .cfg.el.getContext('2d')
  //   .measureText(cfg.label).width;
  // if (parseFloat(cfg.size[0]) <= labelWidth) {
  //   cfg.size[0] = labelWidth + 20;
  // }
  const c = Tsrv.utils.countCharacters(cfg.label);
  // 大于9个汉字调整宽度，小于等于9个 宽150

  const width = Math.round((150 * (c.chinese + c.english / 2)) / 9);
  if (width > 150) {
    cfg.size[0] = width;
  } else {
    cfg.size[0] = 150;
  }
}
function afterNodeUpdate(cfg, node) {}
const beginNode = () => {
  return {
    draw(cfg, group) {
      const size = cfg.size || [160];

      const radius = parseInt(size[0], 10) / 2;
      const mainId = `circle_G${Tsrv.utils.custUUID(16, 16)}`;
      const shape = group.addShape('circle', {
        attrs: {
          id: mainId,
          x: 0,
          y: 0,
          r: radius, // 半径
          stroke: cfg.stroke ? cfg.stroke : '#6ab7ff',
          fill: cfg.fill ? cfg.fill : '#fff'
        }
      });
      if (cfg.label) {
        group.addShape('text', getLabelAttr('begin', true, 0, 0, cfg, mainId));
      }
      const x = 0;
      const y = radius;
      const id = `circle${Tsrv.utils.custUUID(16, 16)}`;
      group.addShape('circle', getNodeAttr('beginOut', x, y, id, 'out', false));
      group.addShape(
        'circle',
        getNodeAttr('beginOut', x, y, null, 'out', true)
      );
      return shape;
    },
    afterDraw: afterNodeDraw,
    update: nodeUpdate,
    afterUpdate: afterNodeUpdate,
    // 设置状态
    setState: getSetState
  };
};
const endNode = () => {
  return {
    draw(cfg, group) {
      const size = cfg.size || [160];

      const radius = parseInt(size[0], 10) / 2;

      const mainId = `circle_G${Tsrv.utils.custUUID(16, 16)}`;
      const shape = group.addShape('circle', {
        attrs: {
          id: mainId,
          x: 0,
          y: 0,
          r: radius, // 半径
          stroke: cfg.stroke ? cfg.stroke : '#6ab7ff',
          fill: cfg.fill ? cfg.fill : '#fff'
        }
      });
      if (cfg.label) {
        group.addShape('text', getLabelAttr('end', true, 0, 0, cfg, mainId));
      }

      const x = 0;
      const y = -radius;
      const id = `circle${Tsrv.utils.custUUID(16, 16)}`;
      group.addShape('circle', getNodeAttr('endIn', x, y, id, 'in', false));
      group.addShape('circle', getNodeAttr('endIn', x, y, id, 'in', true));

      return shape;
    },
    afterDraw: afterNodeDraw,
    update: nodeUpdate,
    afterUpdate: afterNodeUpdate,
    // 设置状态
    setState: getSetState
  };
};
const ifNode = () => {
  return {
    shapeType: 'ifNode',
    draw(cfg, group) {
      const size = cfg.size || [200, 100];

      const width = parseInt(size[0], 10);
      const height = parseInt(size[1], 10);

      const mainId = `polygon_G${Tsrv.utils.custUUID(16, 16)}`;
      const shape = group.addShape('polygon', {
        attrs: {
          id: mainId,
          points: [
            [0, height / 2],
            [-width / 2, 0],
            [0, -height / 2],
            [width / 2, 0]
          ],
          stroke: cfg.stroke ? cfg.stroke : '#6ab7ff',
          fill: cfg.fill ? cfg.fill : '#fff'
        }
      });
      if (cfg.label) {
        group.addShape('text', getLabelAttr('if', true, 0, 0, cfg, mainId));
      }
      // 上
      let x = 0;
      let y = -height / 2;
      const id = `circle${Tsrv.utils.custUUID(16, 16)}`;
      group.addShape('circle', getNodeAttr('ifIn', x, y, id, 'in', false));
      group.addShape('circle', getNodeAttr('ifIn', x, y, id, 'in', true));

      // 下
      x = 0;
      y = height / 2;
      const id2 = `circle${Tsrv.utils.custUUID(16, 16)}`;
      group.addShape('circle', getNodeAttr('ifYes', x, y, id2, 'out', false));
      group.addShape('circle', getNodeAttr('ifYes', x, y, id2, 'out', true));

      // 左
      x = -width / 2;
      y = 0;
      const id3 = `circle${Tsrv.utils.custUUID(16, 16)}`;
      group.addShape('circle', getNodeAttr('ifNo', x, y, id3, 'out', false));
      group.addShape('circle', getNodeAttr('ifNo', x, y, id3, 'out', true));

      x = width / 2;
      y = 0;
      const id4 = `circle${Tsrv.utils.custUUID(16, 16)}`;
      group.addShape('circle', getNodeAttr('ifNo', x, y, id4, 'out', false));
      group.addShape('circle', getNodeAttr('ifNo', x, y, id4, 'out', true));

      return shape;
    },
    afterDraw: afterNodeDraw,
    update: nodeUpdate,
    afterUpdate: afterNodeUpdate,
    setState: getSetState
  };
};
const caseNode = () => {
  return {
    draw(cfg, group) {
      const size = cfg.size || [200, 100];

      const width = parseInt(size[0], 10);
      const height = parseInt(size[1], 10);

      const mainId = `polygon_G${Tsrv.utils.custUUID(16, 16)}`;
      const shape = group.addShape('polygon', {
        attrs: {
          id: mainId,
          points: [
            [width / 3 / 2, height / 2],
            [(-width / 3) * 1.5, height / 2],
            [-width / 3 / 2, -height / 2],
            [(width / 3) * 1.5, -height / 2]
          ],
          stroke: cfg.stroke ? cfg.stroke : '#6ab7ff',
          fill: cfg.fill ? cfg.fill : '#fff'
        }
      });
      if (cfg.label) {
        group.addShape('text', getLabelAttr('case', true, 0, 0, cfg, mainId));
      }

      // 左
      // let x = -width/3
      // let y = 0

      let x = 0;
      let y = -height / 2;
      const id3 = `circle${Tsrv.utils.custUUID(16, 16)}`;
      group.addShape('circle', getNodeAttr('caseIn', x, y, id3, 'in', false));
      group.addShape('circle', getNodeAttr('caseIn', x, y, id3, 'in', true));

      // x = width/3
      // y = 0

      x = 0;
      y = height / 2;
      const id4 = `circle${Tsrv.utils.custUUID(16, 16)}`;
      group.addShape('circle', getNodeAttr('caseOut', x, y, id4, 'out', false));
      group.addShape('circle', getNodeAttr('caseOut', x, y, id4, 'out', true));

      return shape;
    },
    afterDraw: afterNodeDraw,
    update: nodeUpdate,
    afterUpdate: afterNodeUpdate,
    setState: getSetState
  };
};
const exprNode = () => {
  return {
    draw(cfg, group) {
      const size = cfg.size || [200, 100];
      const width = parseInt(size[0], 10);
      const height = parseInt(size[1], 10);
      const mainId = `rect_G${Tsrv.utils.custUUID(16, 16)}`;
      const shape = group.addShape('rect', {
        attrs: {
          id: mainId,
          x: -width / 2,
          y: -height / 2,
          width,
          height,
          stroke: cfg.stroke ?? '#6ab7ff',
          fill: cfg.fill ?? '#fff',
          radius: 4 // 此处必须有fill 不然不能触发事件
        }
      });
      if (cfg.label) {
        group.addShape('text', getLabelAttr('expr', true, 0, 0, cfg, mainId));
      }

      // 上
      let x = 0;
      let y = -height / 2;
      const id1 = `circle${Tsrv.utils.custUUID(16, 16)}`;
      group.addShape('circle', getNodeAttr('exprIn', x, y, id1, 'in', false));
      group.addShape('circle', getNodeAttr('exprIn', x, y, id1, 'in', true));

      // 下
      x = 0;
      y = height / 2;
      const id2 = `circle${Tsrv.utils.custUUID(16, 16)}`;
      group.addShape('circle', getNodeAttr('exprOut', x, y, id2, 'out', false));
      group.addShape('circle', getNodeAttr('exprOut', x, y, id2, 'out', true));

      // 左
      x = -width / 2;
      y = 0;
      const id3 = `circle${Tsrv.utils.custUUID(16, 16)}`;
      group.addShape(
        'circle',
        getNodeAttr('exprIn', x, y, id3, 'inOut', false)
      );
      group.addShape('circle', getNodeAttr('exprIn', x, y, id3, 'inOut', true));

      x = width / 2;
      y = 0;
      const id4 = `circle${Tsrv.utils.custUUID(16, 16)}`;
      group.addShape(
        'circle',
        getNodeAttr('exprOut', x, y, id4, 'inOut', false)
      );
      group.addShape(
        'circle',
        getNodeAttr('exprOut', x, y, id4, 'inOut', true)
      );

      return shape;
    },
    afterDraw: afterNodeDraw,
    update: nodeUpdate,
    afterUpdate: afterNodeUpdate,
    setState: getSetState
  };
};
const nodes = [
  // { nodeName: 'beginNode', nodeConfFun: beginNode },
  // { nodeName: 'endNode', nodeConfFun: endNode },
  { nodeName: 'gIfNode', nodeConfFun: ifNode },
  // { nodeName: 'caseNode', nodeConfFun: caseNode },
  { nodeName: 'gRectNode', nodeConfFun: exprNode }
];

const customNode = {
  init() {
    nodes.forEach(item => {
      G6.registerNode(item.nodeName, item.nodeConfFun());
    });
  }
};

export default customNode;
